﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using BinPacking;
using System.Threading.Tasks;

public class MetalCalc : MonoBehaviour {

	[SerializeField]
	InputField m_ipfLength;

	[SerializeField]
	Button m_plus;

	[SerializeField]
	Button m_minus;

	[SerializeField]
	InputField m_ipfPadding;

	[SerializeField]
	Button m_btnCalc;

	[SerializeField]
	GameObject m_inputTemplate;

	[SerializeField]
	GameObject m_viewContent;

	[SerializeField]
	GameObject m_outputView;

	[SerializeField]
	GameObject m_outputViewContent;

	[SerializeField]
	Text m_outputTemplate;

	Stack<GameObject> m_inputs = new Stack<GameObject>();

	void Start () {
		m_inputTemplate.SetActive(false);

		m_plus.onClick.AddListener(() => {
			var rectTrans = m_viewContent.GetComponent<RectTransform>();
			var copy = Instantiate(m_inputTemplate, rectTrans);
			copy.SetActive(true);
			m_inputs.Push(copy);
			Canvas.ForceUpdateCanvases();
		});

		m_minus.onClick.AddListener(() => {
			if (m_inputs.Count > 0) {
				Destroy(m_inputs.Pop());
				Canvas.ForceUpdateCanvases();
			}
		});

		m_ipfLength.onValidateInput = (string text, int idx, char ch) => { return ch == '-' || ch == '+' ? '\0' : ch; };
		m_ipfPadding.onValidateInput = (string text, int idx, char ch) => { return ch == '-' || ch == '+' ? '\0' : ch; };
		m_inputTemplate.GetComponent<RectTransform>().Find("Length").gameObject.GetComponent<InputField>().onValidateInput = (string text, int idx, char ch) => { return ch == '-' || ch == '+' ? '\0' : ch; };
		m_inputTemplate.GetComponent<RectTransform>().Find("Num").gameObject.GetComponent<InputField>().onValidateInput = (string text, int idx, char ch) => { return ch == '-' || ch == '+' ? '\0' : ch; };

		m_outputView.GetComponentInChildren<Button>().onClick.AddListener(()=>m_outputView.SetActive(false));
		m_btnCalc.onClick.AddListener(Calc);
	}

	void Calc() {
		var items = new List<long>();
		var padding = long.Parse(m_ipfPadding.text);
		var rawLength = long.Parse(m_ipfLength.text);
		rawLength += padding;

		var rectTrans = m_viewContent.GetComponent<RectTransform>();
		for (int idx = 0; idx < rectTrans.childCount; idx++)
		{
			var child = rectTrans.GetChild(idx);
			if (child.gameObject.activeSelf) {
				var lengthStr = child.GetComponent<RectTransform>().Find("Length").GetComponent<InputField>().text;
				var length = long.Parse(lengthStr);
				var num = long.Parse(child.GetComponent<RectTransform>().Find("Num").GetComponent<InputField>().text);
				length += padding;
				if (length <= rawLength) for (int i = 0; i < num; i++) items.Add(length);
			}
		}

		var packer = new BinPacker(items, rawLength);
		packer.TryFit();
		var leastBins = packer.LeastBins;

		m_outputView.SetActive(true);
		var outputViewRect = m_outputViewContent.GetComponent<RectTransform>();
		outputViewRect.DetachChildren();
		foreach (var ret in leastBins)
		{
			var buf = new StringBuilder();
			foreach (var f in ret)
			{
				buf.AppendFormat("{0} | ", f - padding);
			}
			var txt = Instantiate(m_outputTemplate);
			txt.gameObject.SetActive(true);
			txt.GetComponent<Text>().text = buf.ToString();
			txt.GetComponent<RectTransform>().SetParent(outputViewRect);
		}
		Canvas.ForceUpdateCanvases();
	}
}
